package com.zhenai.rocyuan.modules.threadupdown.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.Thread.State;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;

import com.zhenai.rocyuan.modules.threadupdown.BaseSocket;
import com.zhenai.rocyuan.modules.threadupdown.BaseSocketTool;
import com.zhenai.rocyuan.modules.threadupdown.Operation;
import com.zhenai.rocyuan.modules.threadupdown.Users;
import com.zhenai.rocyuan.modules.threadupdown.Utils;

public class Server {
	private ExecutorService exec;
	private ServerSocket server;
	private boolean stop = false;
	private static final Logger log = Logger.getLogger(Server.class);

	public static void main(String[] args) {
		RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
		System.out.println(runtime.getName());

		final Server server2 = new Server();

		// 服务器主线程
		final Thread main = new Thread(new Runnable() {
			public void run() {
				server2.work();
			}
		});
		main.start();

		// 查看服务器主线程工作状态 , 测试中的确出现了 阻塞 :BLOCKED , 不需要的时候可以不开启这个线程
		new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					State state = main.getState();
					log.error("state:" + state);
				}
			}
		}).start();

		// 30s之后强制服务器关闭
		// new Thread(new Runnable() {
		// public void run() {
		// log.debug("进入倒计时,,,,,,");
		// try {
		// Thread.sleep(1000 * 30);
		// } catch (InterruptedException e) {
		// e.printStackTrace();
		// }
		// log.debug("倒计时结束,,,,,,");
		// server2.stop();
		// }
		// }).start();
	}

	/**
	 * 服务器停止工作
	 */
	public void stop() {
		this.stop = true;
		System.out.println("结束吧");
		if (exec != null && !exec.isShutdown()) {
			exec.shutdown();
		}
	}

	/**
	 * 服务器启动工作
	 */
	public void work() {
		try {

			server = new ServerSocket(BaseSocket.SERVER_PORT, BaseSocket.MAX_CONN_COUNT);
			// exec = Executors.newCachedThreadPool();
			exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * BaseSocket.MAX_CONN_COUNT);
			System.out.println("服务器启动");
			Socket client = null;
			while (!stop && !exec.isShutdown() && server != null) {
				client = server.accept();
				client.setTcpNoDelay(true);
				ChatTask task = new ChatTask(client);
				exec.execute(task);
			}
		} catch (IOException e) {
			log.error(e, e);
		}
	}

	class ChatTask implements Runnable, Serializable {
		private static final long serialVersionUID = 1L;
		private Socket socket;
		private Logger log = Logger.getLogger(ChatTask.class);

		public ChatTask(Socket socket) throws IOException {
			this.socket = socket;
		}

		public void run() {
			// while (socket.isConnected() && !socket.isClosed()) {
			// mainWork(socket);
			// }
			if (socket.isConnected() && !socket.isClosed()) {
				mainWork(socket);
			}

		}

		private void mainWork(Socket client) {
			ObjectOutputStream objOut = null;
			ObjectInputStream objIn = null;
			Operation opera = null;
			try {
				SocketAddress address = client.getRemoteSocketAddress();
				log.debug("+++已连接[ " + address + " ].....");

				objOut = new ObjectOutputStream(client.getOutputStream());
				objIn = new ObjectInputStream(client.getInputStream());

				String ip = BaseSocketTool.getClientIp(address);
				// 验证客户端ip
				boolean flag = BaseSocketTool.validateIp(ip);
				objOut.writeBoolean(flag);
				objOut.flush();

				if (flag) {
					Object o = objIn.readObject();
					Users user = null;
					boolean temp = false;
					if (objIn != null && o != null && o instanceof Users) {
						user = (Users) o;
						if (Utils.validateUser(user)) {
							temp = true;
						}
					}
					// 服务器端返回验证结果
					objOut.writeBoolean(temp);
					objOut.flush();

					if (temp) {
						Object object = objIn.readObject();
						if (object instanceof Operation) {
							opera = (Operation) object;
							BaseSocketTool tool = new BaseSocketTool();
							opera = tool.todo(opera, objOut, objIn);
							log.debug("服务器端写入对象");
							tool.writeObject(objOut, opera);
						}
					}
				}
			} catch (Exception e) {
				log.error(e, e);
			} finally {
				try {
					if (objIn != null) {
						objIn.close();
					}
					if (objOut != null) {
						objOut.close();
					}
					if (client != null && client.isConnected()) {
						client.close();
					}
				} catch (IOException e) {
					log.error(e, e);
				}
			}
		}
	}

}